package gwtgaetools.server;

import gwtgaetools.client.comm.GenericMessageInterpreter;
import gwtgaetools.client.comm.GenericRPCService;
import gwtgaetools.shared.model.BaseObject;
import gwtgaetools.shared.model.GenericMessage;
import gwtgaetools.shared.model.PropertyEnum;

import java.util.ArrayList;

import javax.jdo.PersistenceManager;

import com.google.appengine.api.channel.ChannelMessage;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public abstract class GenericServerRPC<
Type,
Message extends GenericMessage<Type>,
MessageProcessor,
MessageInterpreter extends GenericMessageInterpreter<Type, Message, MessageProcessor>
> extends RemoteServiceServlet implements GenericRPCService<Type, Message> {

	private static final long serialVersionUID = 5979504836521760244L;

	protected MessageInterpreter interpreter;
	
	public PushServer<Message> pushServer;
	
	public GenericServerRPC() {
		interpreter = createInterpreter();
		pushServer = new PushServer<Message>(getAppPath());
	}
	
	protected abstract MessageInterpreter createInterpreter();

	public abstract String getAppPath();

	protected <T extends BaseObject<T,PE>, PE extends PropertyEnum<PE,T>> 
	T add(T b) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			pm.makePersistent(b);
			b = pm.detachCopy(b);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return b;
	}

	/**
	 * Send message to client over channel
	 * @param channelKey channel-key
	 * @param message the message to send
	 */
	public void messageClient(String channelKey, Message message) {
		ChannelService channelService = ChannelServiceFactory.getChannelService();
		System.out.println("Server " + channelKey + ": " + message + ".");
		channelService.sendMessage(new ChannelMessage(channelKey, pushServer.encodeMessage(message)));
	}

	public void messageClients(ArrayList<String> ids, Message message) {
		for (String id : ids)
			messageClient(id, message);
	}
	
	@Override public void processMessage(Message m) throws Exception {
			interpreter.processMessage(m);
	}
	
	// Dummy method, should never be called.
	@Override public Message dummyMethod() {
		return null;
	}
	
}
